//
// WormProtocolSession.java
// A pseudo-protocol that models a worm.
// 
//
// @author Michael Liljenstam, ISTS, Dartmouth College
//
// $Id: WormProtocolSession.java,v 1.8 2003/03/08 03:24:48 mili Exp $

package SSF.App.Worm;

import SSF.OS.*;
import SSF.Net.*;
import SSF.Net.Util.*;
import com.renesys.raceway.DML.*;

import SSF.OS.BGP4.Util.*;

// ==== SSF.App.Worm.WormProtocolSession class ==========================/
/**
 * Models the worm infestation in a single host. Connects to the global 
 * epidemic model to receive infection trigger. See <tt>config()</tt> method 
 * for more information on how to set the parameters for the epidemic model.
 *
 * @author Michael Liljenstam, ISTS, Dartmouth College
 */
public class WormProtocolSession extends MacroscopicModelConfigurator 
    implements Configurable {

  /************************** Global model ******************************/

    /*  static MacroscopicModelConfigurator  macroModelConfiger = 
	new MacroscopicModelConfigurator();*/

  //...... Enumeration of states ......................................../
  static final byte   SUSCEPTIBLE = 0;
  static final byte   INFECTED    = 1;
  static final byte   REMOVED     = 2;

  /** Print out debug information for macroscopic model. */
  static boolean              wormModelDebug = false;


  /************************** Attributes ********************************/

  /** Epidemiological state. */
  byte               state = SUSCEPTIBLE;

  /** Host entity where this pseudo-protocol is installed */
  Host               localHost;

  /** Host's NHI address */
  String             localNHI;

  /** AS number this router belongs to. */
  int                asn;

  /** Print out debug information. */
  boolean            debug = false;

  /************************** Methods    ********************************/

  public WormProtocolSession() {
    super();
    //    System.err.println("WormProtocolSession created");
  }



  /** 
   *  Initalize (after config phase). First instance creates global epidemic 
   *  model object and initiates the timer that drives the epidemic model. 
   *  All instances register with the epidemic model so that it can find them 
   *  to trigger infection events.
   */
  public void init() {
    // create worm model
    if (wormModel == null) {
	// create worm model
	init_macroscopic();
    }

    // register this host with the worm model
    if (!stratifiedOn) {
	wormModel.registerHost(this, 1); // set ASN=1 for all
    } else {
	// find out ASN
	asn = AS_descriptor.nh2as(AS_descriptor.get_as_nh((Host) inGraph()));
	// register
	wormModel.registerHost(this, asn);
    }
  }


  /** 
   *  Configure WormProtocolSession. 
   *  Also forwards global configuration of the macroscopic epidemic model to 
   *  MacroscopicModelConfigurator.
   *  <p>
   *  REQUIRED ATTRIBUTES: <br>
   *  <ul>
   *  </ul><p>
   *
   *  OPTIONAL ATTRIBUTES:<br> 
   *  <ul>
   *    <li><b>debug</b> %S      --- "debug true" will switch on debugging 
   *                                 printouts for this session. </li>
   *  </ul><p>
   *
   *  Whenever the <tt>WormProtocolSession</tt> or 
   *  <tt>GatewayProtocolSession</tt> is used, the 
   *  outermost <b>Net</b> <i>must have</i> a global definition of the 
   *  <b>worm_model [ ... ]</b> attribute. The <b>worm_model</b> attributes 
   *  are as follows:
   *
   *  @see MacroscopicModelConfigurator.configGlobalOptions() for more 
   *       details.
   */
  public void config(Configuration cfg) throws configException {
    super.config(cfg);

    //    System.err.println("WormProtocolSession config");

    localHost = (SSF.Net.Host) inGraph();
    localNHI = localHost.nhi;

    // configure global options
    try {
      // get to the top-level Net
      cidrBlock blk = localHost.defined_in_network();
      while (blk.nhi_parent() != null) {
        blk = blk.nhi_parent();
      }
      Configuration globcfg =
            (Configuration)blk.networkConfiguration().findSingle("worm_model");
      configGlobalOptions(globcfg, (Configuration)blk.networkConfiguration());
    } catch (configException cex) {
      System.err.println("Problem configuring macroscopic worm model options");
      cex.printStackTrace();
    }

    // look for debug flag
    try {
      if((cfg.findSingle("debug") != null) && 
	 (((String)cfg.findSingle("debug")).compareTo("true") == 0))
	  debug =  true;
    } catch (configException e) {
	System.err.println("WormProtocolSession: " + e);
    }

  } // config


  /**
   *  Do nothing.
   */
  public boolean push(ProtocolMessage msg, ProtocolSession fromSessn) {
    return true;
  }


  /**
   * Make this host become infected.
   * 
   */
  public void becomeInfected() {
    switch (state) {
    case SUSCEPTIBLE:
      if (debug)
	System.err.println("t: " + getSimTime() 
			   + " Host " + ((Host) this.inGraph()).nhi 
			   + " infected");
      state = INFECTED;
      //      wormModel.registerInfection(this);
      break;
    default:
      System.err.println("Unexpected state: " + state);
      System.exit(-1);
    }
  }


  /**
   *  Get epidemiological state.
   * 
   */
  public byte getState() {
    return state;
  }
}
